/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#ifndef __ATC_CANVAS_HDR__
#define __ATC_CANVAS_HDR__

#include <q3canvas.h>
//Added by qt3to4:
#include <Q3PointArray>

#include <map>
#include <stdexcept>
#include <utility>
#include <vector>

#include "atc.h"
#include "atc_types.h"
#include "canvas_infoblock.h"
#include "map_impl.h"
#include "param_impl.h"


#define AIRCRAFT_MAP      std::map< std::string, AircraftSprite * >
#define AIRCRAFT_MAP_PAIR std::pair< const std::string, AircraftSprite * >
#define DBL_PAIR          std::pair< double, double >
#define LOCATION_VECTOR   std::vector< Location >


namespace atc{

	//
	// class declarations
	//

	class AircraftAgent;
	class AircraftSprite;

	class BearingRangeLine;
	class RequirementTool;
	class ScaleXHair;
	class SectorSprite;
	class Transformation;
	class VectorTool;
	class WayPointSprite;

	struct AircraftParam;
	struct AircraftTypeParam;



	//
	// atc::canvas_error
	//
	struct canvas_error : public std::runtime_error{
		canvas_error(const std::string& msg)
			:std::runtime_error(msg)
		{}
	};



	//
	// atc::Canvas
	//
	class Canvas : public Q3Canvas {
		Q_OBJECT

	private:
		static const int CHUNK_COUNT;

	public:
		Canvas( QObject * = 0, const char * = 0 );
		~Canvas();

	public: // virtual
		void resize( const QRect& );

	public: // initialization
		void set_info_position( GridPosition p ) { _infoPosition = p; }

		void add_time_info();
		void add_score_info();
		
		void add_goal_info(const std::string& a_label = "",
						   const std::string& a_globalRef = "",
						   const std::string& a_text = "");

		void add_tool_info();
		void AddSelfReferentGoalInfo();
		void AddNormativeGoalInfo();
		
		void AddCorrectDecisionsInfo(	const std::string& a_label = "",
										const std::string& a_globalRef = "",
										const std::string& a_text = "");

		void AddIncorrectDecisionsInfo(	const std::string& a_label = "",
										const std::string& a_globalRef = "",
										const std::string& a_text = "");

		void show_info();
		
		BearingRangeLine* add_brl ( int, int );
		BearingRangeLine* add_brl ( AircraftSprite * );
		BearingRangeLine* add_brl ( WayPointSprite * );
		void hook_brl( int, int );
		void hook_brl( AircraftSprite * );
		void hook_brl( WayPointSprite * );
		void select_brl( BearingRangeLine * );
		void remove_brl( BearingRangeLine * );

//		void show_scale( bool );
		void add_scale(	int, int, int, int, int, int );
		void add_scale( int, int, int, int, GridPosition );

		void move_scale( QPoint );

		VectorTool * vector_tool();
		VectorTool * add_vector( AircraftSprite * );
		void move_vector( QPoint );
		void cancel_vector();

		void toggle_srprobe( int = 1 );

		void pause()  { emit pause_request();  }
		void resume() { emit resume_request(); }

		void add_sector       ( const AreaDefinition & );
		void add_active_sector( const AreaDefinition & );
		void add_weather      ( const AreaDefinition& );
		void add_waypoint     ( const std::string&, double, double );
		void add_route        ( const LOCATION_VECTOR & );

		void set_conflict_colour( Colour );
		QColor conflict_colour();
		bool conflict_blink();

		void set_palette( Palette * );
		QColor colour_lookup( ControlState );
		bool blink_lookup( ControlState );

	public: // 
		void add_aircraft( AircraftAgent * );

	public: // interface
		double   to_internal_length( double ) const;
		DBL_PAIR to_internal_point ( const double, const double ) const;
		QPoint   to_internal_qpoint( const double, const double ) const;

		double   to_user_length( double ) const;
		DBL_PAIR to_user_point ( const double, const double ) const;
		QPoint   to_user_qpoint( const double, const double ) const;

	public slots: // [virtual]

		void update_aircraft();

	public slots:
		void set_tool( QString );

	private:
		void build_sector( SectorSprite *, const Q3PointArray &);
		Q3PointArray& area_points( const AreaDefinition &, Q3PointArray & );
		double bearing( QPoint, QPoint ) const;  

		void conflict_detection();
		
		//void register_warning( const char *msg ) { emit warning(msg); }

		void _add_scale( int, int, int, int );

	signals:
		void pause_request();
		void resume_request();

		void event_recorded( KeyValues & );

		// clock info
		void sig_update_clock( long );
		void sig_stop_clock();
		void sig_start_clock();

		// score info
		void sig_update_score( long );
		void update_score_quietly( long );

		// goal info
		void sig_update_goal( long );

		// tool info
		void sig_update_tool(  const QString & );


	private: // members

		AIRCRAFT_MAP _aircraft;

		Transformation *_2internal;

		std::vector< WayPointSprite * >        _waypoints;
		std::list  < BearingRangeLine * >      _brls;

		ScaleXHair       *_scale;
		BearingRangeLine *_brl;
		VectorTool       *_vector;

		Q3CanvasText* _clock;
		Q3CanvasText* _tool_id;
		Q3CanvasText* _tool_name;

		Colour   _conflictColour;
		Palette* _palette;

		InfoBlocks _info;
		GridPosition _infoPosition;
	}; 

	//
	// atc::AircraftMap
	//
	typedef AIRCRAFT_MAP      ACSpriteMap;
	typedef AIRCRAFT_MAP_PAIR ACSpriteMapPair;

	//
	// 
	//
	typedef LOCATION_VECTOR RouteList;

	/*!
	 *
	 */
	typedef std::vector<WayPointSprite*> WayPointVector;
	typedef WayPointVector::iterator WayPointVectorIt;
	typedef WayPointVector::const_iterator WayPointVectorCIt;


	/*!
	 *
	 */
	typedef std::list< BearingRangeLine * > BRLList;
	typedef BRLList::const_iterator BRLListCIt;

}; 


#undef AIRCRAFT_MAP
#undef AIRCRAFT_MAP_PAIR
#undef DBL_PAIR
#undef POINT_VECTOR

#endif 
